package app

import (
	"context"
	"net/http"
	"os"
	"os/signal"
	"proxy_resource_test/config"
	"proxy_resource_test/corn"
	"proxy_resource_test/services"
	"proxy_resource_test/services/mill"
	"syscall"
	"time"

	"github.com/smallnest/rpcx/server"
	"proxy_resource_test/dao"
	"proxy_resource_test/utils/logging"
)

// App 定义服务生命周期方法
type App interface {
	Run() error
	Stop() error
}

// Servers 同时承载 HTTP 和 RPC Server
type Servers struct {
	HTTPHandler http.Handler
	RPCServer   *server.Server
}

// Run 并发启动 HTTP 和 RPC，并优雅关机
func (s *Servers) Run() error {
	// 初始化依赖数据库
	if err := dao.SetUp(context.Background()); err != nil {
		return err
	}

	// 启动cron,仅master执行统计
	if config.AppConfig.Development == "master" {
		corn.Init()
	}
	// 3. 启动 pprof
	go services.TestPProf(config.AppConfig.PprofPort)

	go mill.SetUpWater()

	// 启动 HTTP
	httpSrv := &http.Server{Handler: s.HTTPHandler, Addr: config.AppConfig.Address()}

	logging.Info("HTTP 服务启动: ", httpSrv.Addr)
	httpSrv.ListenAndServe()
	// 等待退出信号
	go func() {
		quit := make(chan os.Signal, 1)
		signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
		<-quit
		logging.Info("收到退出信号，开始关闭...")

		// 优雅关闭
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		httpSrv.Shutdown(ctx)
		s.RPCServer.Close()
		// 关闭 DAO 连接
		dao.Close()
		logging.Info("服务已关闭")
		os.Exit(0)
	}()
	return nil
}

// Stop 可用于命令行停止服务
func (s *Servers) Stop() error {
	s.RPCServer.Close()
	return nil
}
